import datetime
import re
import time

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QFile
from PyQt5.QtWidgets import QGridLayout, QFileDialog, QApplication
import ctypes
import utils


class MainWindow(QtWidgets.QMainWindow):
    # noinspection PyArgumentList
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        # 分割三widget
        self.widget_1 = QtWidgets.QWidget(self)
        self.widget_2 = QtWidgets.QWidget(self)
        self.widget_3 = QtWidgets.QWidget(self)
        # 左
        self.label_1 = QtWidgets.QLabel(self.widget_1)
        self.lineEdit_dll = QtWidgets.QLineEdit(self.widget_1)
        self.lineEdit_dll.setDisabled(True)
        self.lineEdit_file = QtWidgets.QLineEdit(self.widget_1)
        self.lineEdit_file.setDisabled(True)
        self.label_2 = QtWidgets.QLabel(self.widget_1)
        self.pushButton_dll = QtWidgets.QPushButton(self.widget_1)
        self.pushButton_import = QtWidgets.QPushButton(self.widget_1)
        self.pushButton_reset = QtWidgets.QPushButton(self.widget_1)
        self.textEdit_input = QtWidgets.QTextEdit(self.widget_1)
        self.label_6 = QtWidgets.QLabel(self.widget_1)
        # 中
        self.label_3 = QtWidgets.QLabel(self.widget_2)
        self.widget_top = QtWidgets.QWidget(self.widget_2)
        self.radioButton_c = QtWidgets.QRadioButton(self.widget_top)
        self.radioButton_w = QtWidgets.QRadioButton(self.widget_top)
        self.radioButton_n = QtWidgets.QRadioButton(self.widget_top)
        self.buttonGroup_task = QtWidgets.QButtonGroup(self.widget_top)
        self.label_4 = QtWidgets.QLabel(self.widget_2)

        self.widget_middle = QtWidgets.QWidget(self.widget_2)
        self.checkBox_r = QtWidgets.QCheckBox(self.widget_middle)
        self.comboBox_t = QtWidgets.QComboBox(self.widget_middle)
        self.comboBox_j = QtWidgets.QComboBox(self.widget_middle)
        self.label_j = QtWidgets.QLabel(self.widget_middle)
        self.label_t = QtWidgets.QLabel(self.widget_middle)
        self.comboBox_h = QtWidgets.QComboBox(self.widget_middle)
        self.label_h = QtWidgets.QLabel(self.widget_middle)

        self.widget_tips = QtWidgets.QTextBrowser(self.widget_2)
        self.label_tips = QtWidgets.QLabel(self.widget_2)

        self.widget_bottom = QtWidgets.QWidget(self.widget_2)
        self.pushButton_export = QtWidgets.QPushButton(self.widget_bottom)
        self.pushButton_commit = QtWidgets.QPushButton(self.widget_bottom)
        # 右
        self.textBrowser_output = QtWidgets.QTextBrowser(self.widget_3)
        self.label_5 = QtWidgets.QLabel(self.widget_3)

        self.setStyleSheet("background-color:#fefefe;")
        self.resize(1020, 600)
        self.setFixedSize(1020, 600)

        # 加载DLL
        self.default_dll = './lib/core.dll'
        self.core_dll = None
        self.loadDll()

        # 加载UI
        self.setupUi()
        self.setupStyleSheet()

        # 连接信号槽
        self.setConfigConstraint()
        self.loadConnect()

    # noinspection PyArgumentList
    def setupUi(self):
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        # 分割成左中右三个widget
        self.widget_1.setGeometry(QtCore.QRect(10, 10, 340, 580))
        sizePolicy.setHeightForWidth(self.widget_1.sizePolicy().hasHeightForWidth())
        self.widget_1.setSizePolicy(sizePolicy)

        self.widget_2.setGeometry(QtCore.QRect(360, 10, 300, 580))
        sizePolicy.setHeightForWidth(self.widget_2.sizePolicy().hasHeightForWidth())
        self.widget_2.setSizePolicy(sizePolicy)

        self.widget_3.setGeometry(QtCore.QRect(670, 10, 340, 580))
        sizePolicy.setHeightForWidth(self.widget_3.sizePolicy().hasHeightForWidth())
        self.widget_3.setSizePolicy(sizePolicy)
        # 左侧widget
        grid_1 = QGridLayout(self.widget_1)
        # 输入框TextEdit
        grid_1.addWidget(self.label_1, 1, 0, 1, 4)
        grid_1.addWidget(self.textEdit_input, 2, 0, 13, 4)
        # self.textEdit_input.setGeometry(QtCore.QRect(10, 30, 280, 500))

        # 导入文件按钮
        grid_1.addWidget(self.pushButton_import, 15, 0, 1, 2)

        # 选择dll按钮
        grid_1.addWidget(self.pushButton_dll, 15, 2, 1, 1)

        # 重置按钮
        grid_1.addWidget(self.pushButton_reset, 15, 3, 1, 1)

        # 文件路径
        grid_1.addWidget(self.label_2, 16, 0, 1, 1)
        grid_1.addWidget(self.lineEdit_file, 16, 1, 1, 3)

        # dll路径
        grid_1.addWidget(self.label_6, 17, 0, 1, 1)
        grid_1.addWidget(self.lineEdit_dll, 17, 1, 1, 3)
        # 中间widget
        grid_2_base = QGridLayout(self.widget_2)

        # 任务选择
        self.label_3.setText("")
        grid_2_base.addWidget(self.label_3, 1, 0, 1, 0)

        grid_2_base.addWidget(self.widget_top, 2, 0, 3, 0)
        grid_2_top = QGridLayout(self.widget_top)
        grid_2_top.addWidget(self.radioButton_n, 1, 0)
        grid_2_top.addWidget(self.radioButton_w, 2, 0)
        grid_2_top.addWidget(self.radioButton_c, 3, 0)
        self.buttonGroup_task.addButton(self.radioButton_n)
        self.buttonGroup_task.addButton(self.radioButton_w)
        self.buttonGroup_task.addButton(self.radioButton_c)

        # 可选参数
        self.label_4.setText("")
        grid_2_base.addWidget(self.label_4, 5, 0, 1, 0)

        grid_2_base.addWidget(self.widget_middle, 6, 0, 4, 0)
        grid_2_middle = QGridLayout(self.widget_middle)

        grid_2_middle.addWidget(self.label_h, 0, 0, 1, 2)
        grid_2_middle.addWidget(self.comboBox_h, 0, 2)
        grid_2_middle.addWidget(self.label_t, 1, 0, 1, 2)
        grid_2_middle.addWidget(self.comboBox_t, 1, 2)
        grid_2_middle.addWidget(self.label_j, 2, 0, 1, 2)
        grid_2_middle.addWidget(self.comboBox_j, 2, 2)
        grid_2_middle.addWidget(self.checkBox_r, 3, 0, 1, 3)

        for row in range(grid_2_middle.rowCount()):
            grid_2_middle.setRowMinimumHeight(row, 30)

        alphabet = utils.get_alphabet()
        alphabet.append('-')
        for comboBox in [self.comboBox_h, self.comboBox_t, self.comboBox_j]:
            for i in range(len(alphabet)):
                comboBox.addItem("")
                comboBox.setMinimumHeight(25)
        # tips
        grid_2_base.addWidget(self.label_tips, 10, 0, 1, 0)
        self.widget_tips.setMaximumHeight(90)
        grid_2_base.addWidget(self.widget_tips, 11, 0, 3, 0)

        # 确认和导出
        grid_2_base.addWidget(self.widget_bottom, 14, 0, 1, 0)
        grid_2_bottom = QGridLayout(self.widget_bottom)
        grid_2_bottom.addWidget(self.pushButton_commit, 0, 0)
        grid_2_bottom.addWidget(self.pushButton_export, 0, 1)

        # 右侧widget
        grid_3 = QGridLayout(self.widget_3)
        # 输出TextBrowser
        grid_3.addWidget(self.label_5, 1, 0, 1, 2)
        grid_3.addWidget(self.textBrowser_output, 2, 0, 16, 2)

        QtCore.QMetaObject.connectSlotsByName(self)
        self.retranslateUi(self)
        return

    def setupStyleSheet(self):
        font_light = QtGui.QFont()
        font_light.setFamily("微软雅黑 Light")
        font_light.setBold(True)
        font = QtGui.QFont()
        font.setFamily("微软雅黑")
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.widget_1.setStyleSheet(
            ".QWidget{background-color: rgb(254, 254, 254)}"
            ".QWidget{border-radius:10px}"
            ".QWidget{border:2px solid rgb(0, 0, 0)}"
        )
        self.textEdit_input.setFont(font_light)
        self.textEdit_input.setStyleSheet(
            ".QTextEdit{background-color:rgb(238, 238, 238)}"
            ".QTextEdit{border-radius:5px}"
            ".QTextEdit{color:rgba(255, 255, 255，200)}"
        )
        self.pushButton_import.setFont(font)
        self.pushButton_import.setStyleSheet(
            "QPushButton{background-color:rgb(56, 56, 56)}"
            "QPushButton{color: rgb(255, 255, 255)}"
            "QPushButton:hover{background-color:rgb(75, 75, 75)}"
            "QPushButton:pressed{background-color:rgb(90, 90, 90)}"
            "QPushButton:{border-radius: 10px}"
        )
        self.pushButton_dll.setFont(font)
        self.pushButton_dll.setStyleSheet(
            "QPushButton{background-color:rgb(56, 56, 56)}"
            "QPushButton{color: rgb(255, 255, 255)}"
            "QPushButton:hover{background-color:rgb(75, 75, 75)}"
            "QPushButton:pressed{background-color:rgb(90, 90, 90)}"
            "QPushButton:{border-radius: 5px}"
        )
        self.pushButton_reset.setFont(font)
        self.pushButton_reset.setStyleSheet(
            "QPushButton{background-color:rgb(56, 56, 56)}"
            "QPushButton{color: rgb(255, 255, 255)}"
            "QPushButton:hover{background-color:rgb(75, 75, 75)}"
            "QPushButton:pressed{background-color:rgb(90, 90, 90)}"
            "QPushButton:{border-radius: 5px}"
        )
        self.lineEdit_file.setFont(font_light)
        self.lineEdit_file.setStyleSheet(
            ".QLineEdit{background-color:rgb(238, 238, 238)}"
            ".QLineEdit{border-radius:5px}"
            ".QLineEdit{color:rgba(255, 255, 255，200)}"
        )
        self.lineEdit_dll.setFont(font_light)
        self.lineEdit_dll.setStyleSheet(
            ".QLineEdit{background-color:rgb(238, 238, 238)}"
            ".QLineEdit{border-radius:5px}"
            ".QLineEdit{color:rgba(255, 255, 255，200)}"
        )
        self.label_1.setFont(font)
        self.label_1.setStyleSheet(
            ".QLabel{background-color: rgb(255, 255, 255, 0)}"
            ".QLabel{border:2px solid rgb(255, 255, 255, 0)}"
        )
        self.label_2.setFont(font)
        self.label_2.setStyleSheet(
            ".QLabel{background-color: rgb(255, 255, 255, 0)}"
            ".QLabel{border:2px solid rgb(255, 255, 255, 0)}"
        )
        self.label_6.setFont(font)
        self.label_6.setStyleSheet(
            ".QLabel{background-color: rgb(255, 255, 255, 0)}"
            ".QLabel{border:2px solid rgb(255, 255, 255, 0)}"
        )

        self.widget_2.setStyleSheet(
            ".QWidget{background-color: rgb(254, 254, 254)}"
            ".QWidget{border-radius:10px}"
            ".QWidget{border:2px solid rgb(0, 0, 0)}"
        )
        self.widget_top.setStyleSheet(
            ".QWidget{background-color: rgb(254, 254, 254)}"
            ".QWidget{border-radius:5px}"
            ".QWidget{border:1px solid rgb(0, 0, 0)}"
        )
        self.radioButton_n.setFont(font_light)
        self.radioButton_w.setFont(font_light)
        self.radioButton_c.setFont(font_light)
        self.label_h.setFont(font_light)
        self.label_t.setFont(font_light)
        self.label_j.setFont(font_light)
        self.comboBox_h.setFont(font_light)
        self.comboBox_t.setFont(font_light)
        self.comboBox_j.setFont(font_light)
        self.checkBox_r.setFont(font_light)

        self.widget_middle.setStyleSheet(
            ".QWidget{background-color: rgb(254, 254, 254)}"
            ".QWidget{border-radius:5px}"
            ".QWidget{border:1px solid rgb(0, 0, 0)}"
        )
        self.widget_bottom.setStyleSheet(
            ".QWidget{background-color: rgb(254, 254, 254)}"
            ".QWidget{border-radius:5px}"
            ".QWidget{border:0px solid rgb(0, 0, 0)}"
        )
        self.pushButton_commit.setFont(font)
        self.pushButton_commit.setStyleSheet(
            "QPushButton{background-color:rgb(56, 56, 56)}"
            "QPushButton{color: rgb(255, 255, 255)}"
            "QPushButton:hover{background-color:rgb(75, 75, 75)}"
            "QPushButton:pressed{background-color:rgb(90, 90, 90)}"
            "QPushButton:{border-radius: 10px}"
        )
        self.pushButton_export.setFont(font)
        self.pushButton_export.setStyleSheet(
            "QPushButton{background-color:rgb(56, 56, 56)}"
            "QPushButton{color: rgb(255, 255, 255)}"
            "QPushButton:hover{background-color:rgb(75, 75, 75)}"
            "QPushButton:pressed{background-color:rgb(90, 90, 90)}"
            "QPushButton:{border-radius: 10px}"
        )
        self.widget_tips.setFont(font_light)
        self.widget_tips.setStyleSheet(
            ".QTextEdit{background-color:rgb(238, 238, 238)}"
            ".QTextEdit{border-radius:5px}"
            ".QTextEdit{color:rgba(255, 255, 255，200)}"
        )
        self.label_3.setFont(font)
        self.label_3.setStyleSheet(
            ".QLabel{background-color: rgb(255, 255, 255, 0)}"
            ".QLabel{border:2px solid rgb(255, 255, 255, 0)}"
        )
        self.label_4.setFont(font)
        self.label_4.setStyleSheet(
            ".QLabel{background-color: rgb(255, 255, 255, 0)}"
            ".QLabel{border:2px solid rgb(255, 255, 255, 0)}"
        )
        self.label_tips.setFont(font)
        self.label_tips.setStyleSheet(
            ".QLabel{background-color: rgb(255, 255, 255, 0)}"
            ".QLabel{border:2px solid rgb(255, 255, 255, 0)}"
            ".QLabel{color: rgb(220,20,60,100)"
        )

        self.widget_3.setStyleSheet(
            ".QWidget{background-color: rgb(254, 254, 254)}"
            ".QWidget{border-radius:10px}"
            ".QWidget{border:2px solid rgb(0, 0, 0)}"
        )
        self.label_5.setFont(font)
        self.label_5.setStyleSheet(
            ".QLabel{background-color: rgb(255, 255, 255, 0)}"
            ".QLabel{border:2px solid rgb(255, 255, 255, 0)}"
        )
        self.textBrowser_output.setFont(font_light)
        self.textBrowser_output.setStyleSheet(
            ".QTextEdit{background-color:rgb(238, 238, 238)}"
            ".QTextEdit{border-radius:5px}"
            ".QTextEdit{color:rgba(255, 255, 255，200)}"
        )
        return

    # noinspection PyArgumentList,PyShadowingNames
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "单词链统计"))
        self.label_1.setText(_translate("MainWindow", "输入文本"))
        self.label_2.setText(_translate("MainWindow", "文件路径:"))
        self.label_3.setText(_translate("MainWindow", "*选择任务:"))
        self.label_4.setText(_translate("MainWindow", "可选参数:"))
        self.label_5.setText(_translate("MainWindow", "输出文本"))
        self.label_6.setText(_translate("MainWindow", "DLL路径:"))
        self.label_tips.setText(_translate("MainWindow", "提示信息:"))
        self.pushButton_import.setText(_translate("MainWindow", "选择文件"))
        self.pushButton_dll.setText(_translate("MainWindow", "选择DLL"))
        self.pushButton_commit.setText(_translate("MainWindow", "确认"))
        self.pushButton_export.setText(_translate("MainWindow", "导出文件"))
        self.pushButton_reset.setText(_translate("MainWindow", "全部重置"))
        self.radioButton_n.setText(_translate("MainWindow", "-n: 单词链数目"))
        self.radioButton_w.setText(_translate("MainWindow", "-w: 最多单词数量单词链"))
        self.radioButton_c.setText(_translate("MainWindow", "-c: 最多字符数量单词链"))
        self.label_h.setText(_translate("MainWindow", "-h: 指定单词链首字母"))
        self.label_t.setText(_translate("MainWindow", "-t: 指定单词链尾字母"))
        self.label_j.setText(_translate("MainWindow", "-j: 指定均不出现首字母"))
        self.checkBox_r.setText(_translate("MainWindow", "-r: 输入单词是否有隐含环"))

        alphabet = utils.get_alphabet()
        alphabet.append('-')
        for comboBox in [self.comboBox_h, self.comboBox_t, self.comboBox_j]:
            for i in range(len(alphabet)):
                comboBox.setItemText(i, _translate("MainWindow", alphabet[i]))
            comboBox.setCurrentText(_translate("MainWindow", "-"))

    def resetState(self):
        self.textEdit_input.setText("")
        self.textBrowser_output.setText("")
        self.lineEdit_file.setText("")
        self.comboBox_h.setCurrentIndex(26)
        self.comboBox_t.setCurrentIndex(26)
        self.comboBox_j.setCurrentIndex(26)
        self.checkBox_r.setChecked(False)
        self.loadDll()
        self.widget_tips.setText("[Success]: 重置成功")

    def loadDll(self, path=None):
        # 加载默认 DLL
        if path is None:
            try:
                self.core_dll = ctypes.CDLL(self.default_dll)
                self.lineEdit_dll.setText(self.default_dll)
                self.widget_tips.setText("")
            except OSError as e:
                self.core_dll = None
                self.widget_tips.setText(f"[Error]: 未能加载DLL:{e}")
        else:
            try:
                self.core_dll = ctypes.CDLL(path)
                self.lineEdit_dll.setText(path)
                self.widget_tips.setText("")
            except OSError as e:
                self.loadDll()
                self.widget_tips.setText(f"[Error]: 未能加载指定DLL,将重新加载默认DLL:{e}")
        return

    def loadConnect(self):
        self.pushButton_import.clicked.connect(self.handleSelectFile)
        self.pushButton_dll.clicked.connect(self.handleSelectDLL)
        self.pushButton_commit.clicked.connect(self.commitConfig)
        self.radioButton_n.clicked.connect(self.setConfigConstraint)
        self.radioButton_w.clicked.connect(self.setConfigConstraint)
        self.radioButton_c.clicked.connect(self.setConfigConstraint)
        self.pushButton_export.clicked.connect(self.exportFileFromStr)
        self.pushButton_reset.clicked.connect(self.resetState)

    def handleSelectFile(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        file, _ = QFileDialog.getOpenFileNames(self, "选择文件", "", "文本文件(*.txt)",
                                               options=options)
        if len(file) == 1:
            print(file)
            self.lineEdit_file.setText(file[0])
            self.readInput(path=file[0])
        elif len(file) > 1:
            print(file)
            self.widget_tips.setText("[Error]: 不能选择超过一个文件")
        else:
            self.widget_tips.setText("[Error]: 未找到输入文件")

    def handleSelectDLL(self):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        file, _ = QFileDialog.getOpenFileNames(self, "选择文件", "", "动态链接库(*.dll)",
                                               options=options)
        if len(file) == 1:
            self.loadDll(path=file[0])
        elif len(file) > 1:
            self.widget_tips.setText("[Error]: 不能选择超过一个DLL")
        else:
            self.loadDll()

    def setConfigConstraint(self):
        if self.buttonGroup_task.checkedButton() == self.radioButton_w \
                or self.buttonGroup_task.checkedButton() == self.radioButton_c:
            self.comboBox_h.setCurrentIndex(26)
            self.comboBox_t.setCurrentIndex(26)
            self.comboBox_j.setCurrentIndex(26)
            self.checkBox_r.setChecked(False)
            self.comboBox_h.setDisabled(False)
            self.comboBox_t.setDisabled(False)
            self.comboBox_j.setDisabled(False)
            self.checkBox_r.setDisabled(False)
        else:
            self.comboBox_h.setCurrentIndex(26)
            self.comboBox_t.setCurrentIndex(26)
            self.comboBox_j.setCurrentIndex(26)
            self.checkBox_r.setChecked(False)
            self.comboBox_h.setDisabled(True)
            self.comboBox_t.setDisabled(True)
            self.comboBox_j.setDisabled(True)
            self.checkBox_r.setDisabled(True)

    def readInput(self, path):
        with open(path, 'r') as f:
            file_contents = f.read()
            self.textEdit_input.setText(file_contents)

    def commitConfig(self):
        if self.checkInputConfig() < 0:
            return
        code, words = self.genWordsFromStr()
        if code < 0:
            return
        len_w = len(words)
        c_words = (ctypes.c_char_p * len_w)()
        for i in range(len_w):
            c_words[i] = words[i].encode('utf-8')
        c_len = ctypes.c_int(len_w)
        result = (ctypes.c_char_p * 20000)()

        alphabet = utils.get_alphabet()
        alphabet.append('-')

        c_h = ctypes.c_char(alphabet[self.comboBox_h.currentIndex()].encode('utf-8'))
        c_t = ctypes.c_char(alphabet[self.comboBox_t.currentIndex()].encode('utf-8'))
        c_j = ctypes.c_char(alphabet[self.comboBox_j.currentIndex()].encode('utf-8'))
        # 模块交换使用，其实自己的DLL是不用这步转换的
        if alphabet[self.comboBox_h.currentIndex()] == '-':
            c_h = ctypes.c_char(0)
        if alphabet[self.comboBox_t.currentIndex()] == '-':
            c_t = ctypes.c_char(0)
        if alphabet[self.comboBox_j.currentIndex()] == '-':
            c_j = ctypes.c_char(0)
        c_r = ctypes.c_bool(self.checkBox_r.isChecked())
        ret = 0
        t_start = 0
        t_end = 0
        if self.buttonGroup_task.checkedButton() == self.radioButton_n:
            t_start = time.perf_counter()
            ret = self.core_dll.gen_chains_all(c_words, c_len, result)
            t_end = time.perf_counter()
        elif self.buttonGroup_task.checkedButton() == self.radioButton_w:
            t_start = time.perf_counter()
            ret = self.core_dll.gen_chain_word(c_words,
                                               c_len,
                                               result,
                                               c_h, c_t, c_j, c_r)
            t_end = time.perf_counter()
        else:
            t_start = time.perf_counter()
            ret = self.core_dll.gen_chain_char(c_words,
                                               c_len,
                                               result,
                                               c_h, c_t, c_j, c_r)
            t_end = time.perf_counter()

        # 将结果转换为Python类型
        if ret > 20000 or (result[0] is not None and ret == 0):
            res = result[0].decode('utf-8')
            self.widget_tips.setText(
                f"[Failed]: at [{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}]\n 运行失败\n"
                + res)
        else:
            t = ((t_end - t_start) * 1000)
            self.widget_tips.setText(
                f"[Success]: at [{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 运行成功\n用时{t}毫秒")
            res = [result[i].decode('utf-8') for i in range(ret)]
            ans = str(ret) + '\n' + '\n'.join(res)
            self.textBrowser_output.setText(ans)
        return

    def exportFileFromStr(self):
        # 选择保存文件的对话框
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        file_path, _ = QFileDialog.getSaveFileName(
            self, "保存文件", "", "文本文件(*.txt)", options=options
        )
        # 如果用户选择了文件，保存字符串到文件
        outputStr = self.textBrowser_output.toPlainText()
        if not file_path.endswith(".txt"):
            file_path += ".txt"
        file = open(file_path, 'w')
        file.write(outputStr)
        self.widget_tips.setText("[Success]: 导出成功!")

    def checkInputConfig(self):
        r = 0
        if self.core_dll is None:
            self.widget_tips.setText("[Error]: 加载DLL失败，请重新选择DLL文件加载!")
            return -1
        if self.buttonGroup_task.checkedButton() == self.radioButton_w \
                or self.buttonGroup_task.checkedButton() == self.radioButton_c:
            if self.checkBox_r.checkState() is False \
                    and self.comboBox_h.currentIndex() == self.comboBox_t.currentIndex() \
                    and self.comboBox_h.currentIndex() != 26:
                self.widget_tips.setText("[Error]: 没有指定-r参数时，-h与-t参数所选字母不能相同")
                r = -1
            elif self.comboBox_h.currentIndex() == self.comboBox_j.currentIndex() \
                    and self.comboBox_h.currentIndex() != 26:
                self.widget_tips.setText("[Error]: -h和-j参数指定同一字母，出现矛盾")
                r = -1
        elif self.buttonGroup_task.checkedButton() == self.radioButton_n:
            r = 0
        else:
            self.widget_tips.setText("[Error]: 当前未指定任务")
            r = -1
        return r

    def genWordsFromStr(self):
        inputStr = self.textEdit_input.toPlainText()
        if len(inputStr) == 0:
            self.widget_tips.setText("[Error]: 当前没有输入")
            return -1, []
        result = re.findall(r'[A-Za-z]+', inputStr)
        if len(result) == 0:
            self.widget_tips.setText("[Error]: 当前输入不存在合法单词")
            return -1, []
        return 0, result

    def testCoreDll(self):
        words = ["ab", "bc", "cd", "de"]

        len_w = len(words)
        c_words = (ctypes.c_char_p * len_w)()
        for i in range(len_w):
            c_words[i] = words[i].encode('utf-8')
        c_len = ctypes.c_int(len_w)
        result = (ctypes.c_char_p * 20000)()
        c_h = ctypes.c_char('b'.encode('utf-8'))
        c_t = ctypes.c_char(0)
        c_j = ctypes.c_char(0)
        c_r = ctypes.c_bool(False)
        chain_len = self.core_dll.gen_chain_char(c_words,
                                                 c_len,
                                                 result,
                                                 c_h, c_t, c_j, c_r)
        # 将结果转换为Python类型
        if chain_len == 0:
            print("gen_chain_word failed")
        else:
            res = [result[i].decode('utf-8') for i in range(chain_len)]
            print(res)
